/*
 *  $Id$

    Copyright (C) 2008  Nathaniel Waisbrot

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package termint.gui.window;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;

import termint.brains.DungeonFeatureListener;
import termint.brains.RoomListener;
import termint.brains.StatsListener;
import termint.game.NHObject;
import termint.game.dungeon.Feature;
import termint.game.dungeon.Room;

/**
 * @author Nathaniel Waisbrot
 *
 */
public class LevelNotes extends Window implements StatsListener, RoomListener, DungeonFeatureListener {
	final TreeItem levels;
	final Map<String,TreeItem> seenLevels = new HashMap<String,TreeItem>(70);
	final Tree tree;
	TreeItem currentLevel;
	public LevelNotes(Shell parent) {
		super(parent.getDisplay());
		setText("Level notes");
		setSize(450, 300);
		window.setLayout(new FillLayout());
		this.tree = new Tree(window, SWT.BORDER); //treeViewer.getTree();
		this.levels = new TreeItem(tree,SWT.NORMAL);
		this.levels.setText("Levels");
		this.levels.setExpanded(true);
	}
	
	/* (non-Javadoc)
	 * @see termint.brains.StatsListener#dungeonLevel(int)
	 */
	public void dungeonLevel(int dlvl) {
		String levName = String.valueOf(dlvl);
		TreeItem level = seenLevels.get(levName);
		if (level == null) {
			level = new TreeItem(this.levels, SWT.NORMAL);
			level.setText(levName);
			seenLevels.put(levName, level);
		}
		this.currentLevel = level;
		expandOnlySubtree(this.currentLevel);
		this.redraw();
	}
	
	/**
	 * Expand this item and children, and collapse everything else
	 * @param ti
	 */
	private void expandOnlySubtree(TreeItem ti) {
		// expand this and all children
		expandAllChildren(ti);
		// now walk up the tree collapsing everything else
		TreeItem child = ti;
		for (TreeItem parent = child.getParentItem(); parent != null; child = parent, parent = child.getParentItem()) {
			for (int i = 0; i < parent.getItemCount(); i++) {
				if (!parent.getItem(i).equals(child)) {
					parent.getItem(i).setExpanded(false);
				}
			}
			parent.setExpanded(true);
		}
	}
	
	/** expand this item and all its children, recursively */
	private void expandAllChildren(TreeItem ti) {
		ti.setExpanded(true);
		for (int i = 0; i < ti.getItemCount(); i++)
			expandAllChildren(ti.getItem(i));
	}


	// Don't care about these Stats-line features:
	public void gold(int gold) {}
	public void hitpoints(int current, int max) {}
	public void power(int current, int max) {}
	public void ac(int ac) {}
	public void exp(int exp) {}
	public void turn(int turn) {}
	public void stats(int str, int dex, int con, int in, int wis, int cha) {}

	@Override
	public void featureDetected(Feature feature) {
		if (currentLevel == null)
			return; // corner case where we see a feature before we've ever seen the stat-line
		int index = currentLevel.getItemCount();
		for (TreeItem child : currentLevel.getItems()) {
			if (child.getData().equals(feature))
				return; // exact match means we're done
			if (child.getData() instanceof Feature) { // some kind of Feature
				Feature knownFeature = (Feature) child.getData();
				if (!knownFeature.locationKnown() && knownFeature.getVTElement().equals(feature.getVTElement())) {
					// same VTE means they're the same, but the one we're already aware of has only been heard
					index = currentLevel.indexOf(child);
					currentLevel.clear(index, true);
					break;  // shouldn't need to scan elsewhere
				}
			}
		}
		TreeItem ti = new TreeItem(currentLevel, SWT.NORMAL, index);
		ti.setData(feature);
		ti.setText(feature.toString());
		currentLevel.setExpanded(true);
	}

	@Override
	public void genericFeature(Class<? extends Feature> class1) {
		addGenericObject(class1);
	}

	@Override
	public void roomDetected(Room room) {
		// TODO Auto-generated method stub
		
	}
	/* (non-Javadoc)
	 * @see termint.brains.RoomListener#genericRoom(java.lang.Class)
	 */
	@Override
	public void genericRoom(Class<? extends Room> class1) {
		addGenericObject(class1);
	}
	
	private void addGenericObject(Class<? extends NHObject> clazz) {
		NHObject obj;
		try {
			obj = clazz.newInstance();
		} catch (InstantiationException | IllegalAccessException e) {
			throw new RuntimeException("Error instantiating class "+clazz, e);
		}
		for (TreeItem child : currentLevel.getItems()) {
			if (child.getData().getClass().equals(clazz))
				return;
		}
		TreeItem newFeature= new TreeItem(currentLevel, SWT.NONE);
		newFeature.setText(obj.toString());
		newFeature.setData(obj);
		currentLevel.setExpanded(true);
	}
}
